
import Foundation
import TunnelKitCore
import TunnelKitManager
import TunnelKitOpenVPN
import ZZBase
import Flutter

/// 共享group
let appGroup = "group.czz.test.DoraVPN"
/// VPN Target的bundleid
let tunnelIdentifier = "com.baboon.yoyovpn.test.HVNPackTunnel"

class HCVNConnectManager: NSObject{
    func initVPN() {
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(VPNStatusDidChange(notification:)),
            name: VPNNotification.didChangeStatus,
            object: nil
        )
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(VPNDidFail(notification:)),
            name: VPNNotification.didFail,
            object: nil
        )
    }
    static let share = HCVNConnectManager()

    private let vpn = NetworkExtensionVPN()

    private var vpnStatus: VPNStatus = .disconnected {
        didSet{
            HCVNChannelManager.vpnStatusChanged(vpnStatus)
        }
    }

    @objc private func VPNStatusDidChange(notification: Notification) {
        vpnStatus = notification.vpnStatus
        print("VPNStatusDidChange: \(vpnStatus)")
    }

    @objc private func VPNDidFail(notification: Notification) {
        print("VPNStatusDidFail: \(notification.vpnError.localizedDescription)")
        HCVNChannelManager.vpnError()
    }
    deinit {
        deinitVPN()
    }

    func hvn_disconnect() {
        Task {
            await vpn.disconnect()
        }
    }

    private var currVpn: String?

    func hvn_connect(_ vpnModel: String){
        currVpn = vpnModel
        guard let config = makeConfig() else {
            HCVNChannelManager.vpnError()
            return
            }
        Task {
            let extra = NetworkExtensionExtra()
            try await vpn.reconnect(tunnelIdentifier, configuration: config, extra: extra, after: .seconds(2) )
        }
    }

    func hvn_prepare(){
        Task { // 检查VPN链接状态
           await vpn.prepare()
        }
    }

    private func makeConfig() -> OpenVPN.ProviderConfiguration?{
        guard let path = self.currVpn else { return nil}
//        let path: String = ZZFile.filePath(for: .bundle, filename: "\(vpn.filename).ovpn")
        guard let pathUrl = zz_url(file: path) else { return nil }

        guard ZZFile.exists(url: pathUrl) else {
            return nil
        }
        guard
            let builder = try? OpenVPN.ConfigurationParser.parsed(fromURL: pathUrl)
        else {
            return nil
        }
        let cfg = builder.configuration

        var providerConfiguration = OpenVPN.ProviderConfiguration(Bundle.appName, appGroup: appGroup, configuration: cfg)
        providerConfiguration.shouldDebug = true
        providerConfiguration.masksPrivateData = false
        return providerConfiguration
    }


    func deinitVPN(){
        NotificationCenter.default.removeObserver(self, name: VPNNotification.didChangeStatus, object: nil)
        NotificationCenter.default.removeObserver(self, name: VPNNotification.didFail, object: nil)
    }


}

extension VPNStatus{
    var rawStatusNum: Int{
        switch self {
            case .connected:
                return 0
            case .connecting:
                return 1
            case .disconnected:
                return 2
            case .disconnecting:
                return 3
        }
    }
}

extension Bundle{
    static var appName: String {
        let appName = Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String
        return appName ?? Bundle.zz_bundleName
    }
}
